package gui.utilities;

/*
 * 	Copyright (c) 2010, Custom Swing Components
 * 	All rights reserved.
 * 
 * 	Redistribution and use in source and binary forms, with or without
 * 	modification, are permitted provided that the following conditions are met:
 * 		* Redistributions of source code must retain the above copyright
 *   	  notice, this list of conditions and the following disclaimer.
 * 		* Redistributions in binary form must reproduce the above copyright
 *   	  notice, this list of conditions and the following disclaimer in the
 *        documentation and/or other materials provided with the distribution.
 * 		* Neither the name of Custom Swing Components nor the
 *        names of its contributors may be used to endorse or promote products
 *        derived from this software without specific prior written permission.
 *      * Redistributions must also adhere to the terms and conditions of the 
 *        specific distribution licenses purchased from Custom Swing Components. 
 * 	      (be it developer, enterprise or source code). 
 * 
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL CUSTOM SWING COMPONENTS BE LIABLE FOR ANY
 *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * Additional Terms And Conditions.
 *
 * 1. Conditions
 * The purchase of a license for a component from Custom Swing Components entitles you to the following: 
 *   1.1. You may use the component on as many projects as you desire. There are no restrictions regarding the number of deployments, and you may bundle the component as part of your software, be it commercial or personal.
 *   1.2. Once you have purchased a component, there is no limit on how many times you may download the Java archive or its supporting documentation.
 *   1.3. 3 months free email support for the purchased component. Additional support will require the purchase of an extended support contract.
 *   1.4. Receive bug fixes and updates for the version of the component purchased. Note that this only includes increments of the component's minor version. To illustrate this, if you purchase version 1.0 of a specific component, you are entitled to all future minor updates (i.e. 1.1, 1.2 ... 1.n).
 *   1.5. In the event that a major version is released within 3 months of you purchasing the previous version, you will be automatically entitled to the new version. To illustrate this, if you purchase version 1.0 of a specific component, you are entitled to version 2.0 for free, if version 2.0 is released within 3 months of your purchase of version 1.0.
 *
 * 2. Restrictions
 * Restrictions apply to all types of licenses:
 *   2.1. You may not directly resell licensed component to other individuals or entities. To illustrate this, you may not sell the Java archive to third parties. Please note that this does not restrict you from including the component in commercial software; it prevents you directly selling the archive to other third parties.
 *   2.2. If the deployment of your software directly exposes the API of the component to third party developers, there may be an additional deployment fee. To illustrate this, if you sell a product whose primary target is developers, they will gain access to the licensed component and be able to use it in their own software. Please note that this does not restrict you from including the component in commercial software; it is intended to prevent other third party developers from making use of components that they have not purchased.
 *   2.3. A license may not be automatically transferred. An enterprise license is granted to a named enterprise and may not be transferred to another enterprise. A developer license is granted to a named developer and may not be transferred to another developer. Custom Swing Components does not support a floating license. Please contact us directly if you need to transfer a license.
 *
 * 3. License Types
 * At present there are 3 types of licenses available: developer, enterprise and source code.
 *   3.1. A developer license entitles a single named developer to make use of the licensed components.
 *   3.2. An enterprise license entitles all developers within the enterprise to make use of the licensed components.
 *   3.3. A source code license is available and applies on an enterprise scale; please contact us for more details.
 *
 * If you have additional questions regarding the licensing, please feel free to contact us directly.
 */
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.Shape;
import java.math.BigDecimal;

import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

import com.javaswingcomponents.framework.painters.gloss.Gloss;
import com.javaswingcomponents.framework.shapes.StarShape;
import com.javaswingcomponents.rater.JSCRater;
import com.javaswingcomponents.rater.listener.RatingChangeEvent;
import com.javaswingcomponents.rater.listener.RatingChangeListener;
import com.javaswingcomponents.rater.model.DefaultRaterModel;
import com.javaswingcomponents.rater.model.DefaultRaterModel.Selection;
import com.javaswingcomponents.rater.plaf.RaterUI;
import com.javaswingcomponents.rater.plaf.basic.BasicRaterUI;
import javax.swing.JLabel;

/**
 * The Class CodeExample.
 */
public class Rater extends JPanel {

    private JSCRater rater;
    private DefaultRaterModel raterModel;
    private JLabel votesLabel;
    private int voters;

    /**
     * Instantiates a new code example.
     */
    public Rater(int rating, int voters) {
        rater = new JSCRater();
        this.voters = voters;
        rater.setBorder(new EmptyBorder(2, 2, 2, 2));
        rater.setEnabled(true);
        //howToListenForChanges();
        howToChangeTheLookAndFeel();
        setRaterModel(rating);
        setVotersPanel(voters);
    }

    /**
     * It can be useful to be notified when changes occur to the rater's rating. To do so we simply add a new
     * RatingChangeListener.
     *
     * @param rater
     */
    private void howToListenForChanges() {
        rater.addRatingChangeListener(new RatingChangeListener() {
            @Override
            public void ratingChanged(RatingChangeEvent ratingChangeEvent) {
                JSCRater rater = ratingChangeEvent.getSource();
                BigDecimal oldValue = ratingChangeEvent.getOldValue();
                BigDecimal newValue = ratingChangeEvent.getNewValue();

                System.out.println("rater value changed from " + oldValue.toPlainString() + " to " + newValue.toPlainString());
            }
        });
    }

    /**
     * You can change the look and feel of the component by changing its ui. In this example we will change
     * the UI to the BasicUI
     *
     * @param rater
     */
    private void howToChangeTheLookAndFeel() {
        //We create a new instance of the UI
        RaterUI newUI = BasicRaterUI.createUI(rater);
        //We set the UI
        rater.setUI(newUI);
    }

    /**
     * The rater is packaged with a default rater model. This method will highlight some of the setting you
     * can change on the model.
     *
     * @param rater
     */
    private void setRaterModel(int rating) {
        raterModel = new DefaultRaterModel();

        //this will change the number of shapes to 7.
        raterModel.setNumShapes(5);

        //this will set the rating of the rater to 3. 
        //Note this method is also available on the rater directly.
        raterModel.setRating(new BigDecimal(rating));

        //The DefaultRater allows the developer to specify
        //if the user may select whole shapes, half shapes or quarter shapes.
        raterModel.setSelection(Selection.FULL);

        rater.setRaterModel(raterModel);
    }

    public int getRating() {
        return raterModel.getRating().intValue();
    }

    public void setRating(int rating) {
        raterModel.setRating(new BigDecimal(rating));
    }

    /**
     * The gloss is the transparent shape drawn over the rater's shapes In this example we create a new star
     * shape gloss. The gloss is essentially just a shape with a gloss opacity and gloss color fields.
     *
     * @param rater
     */
    private void howToChangeTheGloss() {
        //our custom gloss will use an opacity of 20%
        //and the color white
        Gloss customGloss = new Gloss(0.2f, Color.WHITE) {
            @Override
            public Shape getGlossShape(Rectangle bounds) {
                StarShape starShape = new StarShape();
                starShape.setOutterRadius(0.7f);
                starShape.setInnerRadius(0.4f);
                return starShape.getShape(bounds);
            }
        };

        //now we set the gloss
        rater.setGloss(customGloss);
    }

    @Override
    public void setEnabled(boolean bln) {
        super.setEnabled(bln); //To change body of generated methods, choose Tools | Templates.
        rater.setEnabled(bln);
    }

    /**
     * This method will document the remaining useful methods that can be applied to the rater.
     *
     * @param rater
     */
    private void howToCustomizeTheRater() {
        //will set the padding between the shapes to 1 pixel
        rater.setShapePadding(1);

        //toggles if the rater is animated
        rater.setAnimated(true);

        //toggles if the rater renders a drop shadow (expensive)
        rater.setDrawShadow(true);

        //toggles if the rater should react when the mouse
        //is over the rater.
        rater.setListenForMouseMovement(true);

        //sets the color of the shape's border 
        rater.setBorderColor(Color.GRAY);

        //sets the color of the shape's mouseover border 
        rater.setMouseOverBorderColor(Color.WHITE);

        //you can also change the shape's border stroke
        //and mouse over border stroke
        //the code changes the stroke thickness to 2 pixels
        rater.setBorderStroke(new BasicStroke(2f));
        rater.setMouseOverBorderStroke(new BasicStroke(2f));
    }

    private void initVotersLabel(int voters) {
        votesLabel = new JLabel();
        votesLabel.setText("(" + voters + " Votes)");
        votesLabel.setFont(new java.awt.Font("Trebuchet MS", 0, 12)); // NOI18;
        votesLabel.setForeground(Color.WHITE);
        add(votesLabel);
        votesLabel.setVisible(false);
        votesLabel.setVisible(true);
    }

    public void setVoters(int voters) {
        this.voters = voters;
        setVotersPanel(voters);
    }

    public int getVoters() {
        return voters;
    }

    private void setVotersPanel(int voters) {
        removeAll();
        setLayout(new GridLayout(1, (voters >= 0 ? 2 : 1), 0, 0));
        add(rater);
        if (voters >= 0) {
            initVotersLabel(voters);
        }
        setOpaque(false);
    }
}
